package com.kexio.dynamic.permission.rule;

import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 权限规则解析器
 * 
 * 负责解析各种类型的权限规则表达式
 * 
 * @author Kexio
 * @since 1.0.0
 */
@Component
public class RuleParser {

    private final ExpressionParser spelParser = new SpelExpressionParser();
    
    // 表达式缓存
    private final Map<String, Expression> expressionCache = new ConcurrentHashMap<>();
    
    // Groovy脚本缓存
    private final Map<String, Object> scriptCache = new ConcurrentHashMap<>();

    /**
     * 解析SpEL表达式
     * 
     * @param expression SpEL表达式字符串
     * @return 解析后的表达式对象
     */
    public Expression parseSpelExpression(String expression) {
        if (!StringUtils.hasText(expression)) {
            throw new IllegalArgumentException("SpEL表达式不能为空");
        }
        
        return expressionCache.computeIfAbsent(expression, expr -> {
            try {
                return spelParser.parseExpression(expr);
            } catch (Exception e) {
                throw new RuntimeException("SpEL表达式解析失败: " + expr, e);
            }
        });
    }

    /**
     * 解析Groovy脚本
     * 
     * @param script Groovy脚本字符串
     * @return 编译后的脚本对象
     */
    public Object parseGroovyScript(String script) {
        if (!StringUtils.hasText(script)) {
            throw new IllegalArgumentException("Groovy脚本不能为空");
        }
        
        return scriptCache.computeIfAbsent(script, scriptContent -> {
            try {
                groovy.lang.GroovyShell shell = new groovy.lang.GroovyShell();
                return shell.parse(scriptContent);
            } catch (Exception e) {
                throw new RuntimeException("Groovy脚本解析失败: " + script, e);
            }
        });
    }

    /**
     * 解析JavaScript脚本
     * 
     * @param script JavaScript脚本字符串
     * @return 编译后的脚本对象
     */
    public Object parseJavaScript(String script) {
        if (!StringUtils.hasText(script)) {
            throw new IllegalArgumentException("JavaScript脚本不能为空");
        }
        
        return scriptCache.computeIfAbsent(script, scriptContent -> {
            try {
                javax.script.ScriptEngine engine = new javax.script.ScriptEngineManager().getEngineByName("javascript");
                if (engine == null) {
                    engine = new javax.script.ScriptEngineManager().getEngineByName("nashorn");
                }
                if (engine == null) {
                    engine = new javax.script.ScriptEngineManager().getEngineByName("graal.js");
                }
                if (engine == null) {
                    throw new RuntimeException("未找到JavaScript引擎");
                }
                return ((javax.script.Compilable) engine).compile(scriptContent);
            } catch (Exception e) {
                throw new RuntimeException("JavaScript脚本解析失败: " + script, e);
            }
        });
    }

    /**
     * 解析简单条件表达式
     * 
     * @param condition 条件表达式
     * @return 解析后的条件对象
     */
    public SimpleCondition parseSimpleCondition(String condition) {
        if (!StringUtils.hasText(condition)) {
            throw new IllegalArgumentException("简单条件表达式不能为空");
        }
        
        try {
            return SimpleCondition.parse(condition);
        } catch (Exception e) {
            throw new RuntimeException("简单条件解析失败: " + condition, e);
        }
    }

    /**
     * 验证表达式语法
     * 
     * @param expression 表达式
     * @param type       表达式类型
     * @return 验证结果
     */
    public ValidationResult validateExpression(String expression, PermissionRule.RuleType type) {
        if (!StringUtils.hasText(expression)) {
            return ValidationResult.error("表达式不能为空");
        }
        
        try {
            switch (type) {
                case SPEL:
                    parseSpelExpression(expression);
                    break;
                case GROOVY:
                    parseGroovyScript(expression);
                    break;
                case JAVASCRIPT:
                    parseJavaScript(expression);
                    break;
                case SIMPLE:
                    parseSimpleCondition(expression);
                    break;
                default:
                    return ValidationResult.error("不支持的表达式类型: " + type);
            }
            
            return ValidationResult.success();
            
        } catch (Exception e) {
            return ValidationResult.error("表达式验证失败: " + e.getMessage());
        }
    }

    /**
     * 清理表达式缓存
     */
    public void clearCache() {
        expressionCache.clear();
        scriptCache.clear();
    }

    /**
     * 获取缓存统计信息
     * 
     * @return 缓存统计
     */
    public CacheStats getCacheStats() {
        CacheStats stats = new CacheStats();
        stats.setExpressionCacheSize(expressionCache.size());
        stats.setScriptCacheSize(scriptCache.size());
        return stats;
    }

    /**
     * 简单条件表达式
     */
    public static class SimpleCondition {
        private String field;
        private String operator;
        private Object value;

        public static SimpleCondition parse(String condition) {
            if (!StringUtils.hasText(condition)) {
                throw new IllegalArgumentException("条件表达式不能为空");
            }
            
            condition = condition.trim();
            
            // 支持的操作符（按长度降序，避免匹配问题）
            String[] operators = {"==", "!=", ">=", "<=", ">", "<", "contains", "startsWith", "endsWith", "matches"};
            
            for (String op : operators) {
                int index = condition.indexOf(op);
                if (index > 0) {
                    SimpleCondition simpleCondition = new SimpleCondition();
                    simpleCondition.field = condition.substring(0, index).trim();
                    simpleCondition.operator = op;
                    String valueStr = condition.substring(index + op.length()).trim();
                    
                    // 解析值
                    simpleCondition.value = parseValue(valueStr);
                    
                    return simpleCondition;
                }
            }
            
            throw new IllegalArgumentException("无法解析条件表达式: " + condition);
        }
        
        private static Object parseValue(String valueStr) {
            if (valueStr.startsWith("'") && valueStr.endsWith("'")) {
                return valueStr.substring(1, valueStr.length() - 1);
            }
            if (valueStr.startsWith("\"") && valueStr.endsWith("\"")) {
                return valueStr.substring(1, valueStr.length() - 1);
            }
            if ("true".equalsIgnoreCase(valueStr)) {
                return true;
            }
            if ("false".equalsIgnoreCase(valueStr)) {
                return false;
            }
            if ("null".equalsIgnoreCase(valueStr)) {
                return null;
            }
            
            // 尝试解析数字
            try {
                if (valueStr.contains(".")) {
                    return Double.parseDouble(valueStr);
                } else {
                    return Long.parseLong(valueStr);
                }
            } catch (NumberFormatException e) {
                // 作为字符串返回
                return valueStr;
            }
        }

        // Getters and Setters
        public String getField() { return field; }
        public void setField(String field) { this.field = field; }
        
        public String getOperator() { return operator; }
        public void setOperator(String operator) { this.operator = operator; }
        
        public Object getValue() { return value; }
        public void setValue(Object value) { this.value = value; }
    }

    /**
     * 验证结果
     */
    public static class ValidationResult {
        private boolean success;
        private String message;

        public static ValidationResult success() {
            ValidationResult result = new ValidationResult();
            result.success = true;
            return result;
        }

        public static ValidationResult error(String message) {
            ValidationResult result = new ValidationResult();
            result.success = false;
            result.message = message;
            return result;
        }

        // Getters
        public boolean isSuccess() { return success; }
        public String getMessage() { return message; }
    }

    /**
     * 缓存统计信息
     */
    public static class CacheStats {
        private int expressionCacheSize;
        private int scriptCacheSize;

        // Getters and Setters
        public int getExpressionCacheSize() { return expressionCacheSize; }
        public void setExpressionCacheSize(int expressionCacheSize) { this.expressionCacheSize = expressionCacheSize; }
        
        public int getScriptCacheSize() { return scriptCacheSize; }
        public void setScriptCacheSize(int scriptCacheSize) { this.scriptCacheSize = scriptCacheSize; }
    }
}
